﻿using System;
using System.Collections.Generic;
using Cinemachine;
using com.yoozoo.gta.Extension.UGUI.ScreenOrientationEx;
using UnityEngine;
using Yoozoo.Core.Extensions.Engine;
using Yoozoo.Framework.Core;
using Random = System.Random;

namespace Gameplay.PVE.Survivor
{
    public class BattleEventManager: BattleSingleton<BattleEventManager>
    {
        public class BattleEventData
        {
            public float addTime;
            public float lastTriggerTime;
            public RpgMissionStageEventConfig config;
            public int triggerTimes;
            public bool valid;
            public bool showUIEvent;
            public bool isEventFinish;
            public BattleUnit targetUnit;

            public bool IsBattleStartEvent()
            {
                return config.event_condition == (int)EBattleEventCondition.Timer && BattleEventManager.Instance.GetConfigValue(config.event_condition_value,0) == 0;
            }
        }
        private List<BattleEventData> eventList = new List<BattleEventData>();
        private EnemyRandomSpawner enemyRandomSpawner;
        
        private Dictionary<int, MapInteractableData> interactableDic = new Dictionary<int, MapInteractableData>();

        private bool enabled = true;
        
		public void Initialize()
        {
            
        }

        public void SetEnabled(bool value)
        {
            enabled = value;
            enemyRandomSpawner?.SetEnabled(value);
        }

        public void OnStageStart(int stageId)
        {
            foreach(var item in interactableDic)
            {
                item.Value.OnStageStart(stageId);
            }
            Update();
        }
        
        public void SetInteractable(Dictionary<int,MapInteractableData> interactableDic)
        {
            this.interactableDic = interactableDic;
            foreach(var item in interactableDic)
            {
                item.Value.Init();
            }
        } 
        
        public override void Update()
        {
            if (!enabled)
            {
                return;
            }

            if (StageManager.Instance.IsPause)
            {
                return;
            }
            for (int i = 0; i < eventList.Count; i++)
            {
                var data = eventList[i];
                if (CheckCanTrigger(data))
                {
                    data.triggerTimes++;
                    data.lastTriggerTime = TimeManager.time;
                    data.isEventFinish = true;
                    TriggerEvent(data.config,data);
                }

                if (data.showUIEvent)
                {
                    var content = GetUIEventContent(data);
                    var value = GetUIEventProgress(data);
                    StageManager.Instance.UpdateProgressUI(content,value);
                }
            }
            foreach(var interactable in interactableDic)
            {
                //interactable.Value.Update();
                var hasFinish = interactable.Value.UpdateInteractable();
                /*if (hasFinish)
                {
                    MissionManager.Instance.InteractableComplete(interactable.Key);
                }*/
            }
            enemyRandomSpawner?.Update();
        }

        public bool HasUnfinishedBattleStartEvent()
        {
            for (int i = 0; i < eventList.Count; i++)
            {
                var evt = eventList[i];
                if (evt.IsBattleStartEvent() && (!evt.isEventFinish))
                {
                    return true;
                }
            }
            return false;
        }

        public void AddEvent(int eventId)
        {
            var config = BattleConfigManager.Instance.GetStageEventConfig(eventId);
            if (config == null)
            {
                return;
            }

            eventList.Add(new BattleEventData
            {
                addTime = TimeManager.time,
                config = config,
                triggerTimes = 0,
                valid = true,
            });
            if (config.event_trigger == (int)EBattleEventType.PlayTimeline && config.event_condition == (int)EBattleEventCondition.Timer && GetConfigValue(config.event_condition_value,0) == 0)
            {
                needLoadTimeline = true;
            }
        }

        private bool CheckCanTrigger(BattleEventData data)
        {
            if (!data.valid)
            {
                return false;
            }

            if (data.config.event_condition == (int)EBattleEventCondition.Timer)
            {
                var checkTime = data.addTime;
                if (data.lastTriggerTime != 0)
                {
                    checkTime = data.lastTriggerTime;
                }
                var time = GetConfigValue(data.config.event_condition_value, 0);
                var loopTimes = GetConfigValue(data.config.event_condition_value, 1);
                if (loopTimes == 0)
                {
                    loopTimes = 1;
                }
                if (loopTimes > 0 && data.triggerTimes >= loopTimes)
                {
                    data.valid = false;
                    return false;
                }
                if (TimeManager.time - checkTime >= time)
                {
                    return true;
                }
            }
            else if (data.config.event_condition == (int)EBattleEventCondition.EnterRegion)
            {
                if (data.lastTriggerTime != 0)
                {
                    return false;
                }
                var regionId = data.config.event_condition_value[0];
                var region = StageManager.Instance.GetRegion(regionId);
                if (region != null)
                {
                    var teamPosition = StageManager.Instance.TeamGroup.Position;
                    var specialId = GetConfigValue(data.config.event_condition_value, 1);
                    if (specialId > 0)
                    {
                        if (data.targetUnit == null)
                        {
                            data.targetUnit = UnitManager.Instance.GetUnitByHeroId(specialId);
                        }

                        if (data.targetUnit != null)
                        {
                            return BattleHelper.IsInRegion(data.targetUnit.position, region);
                        }
                    }
                    else
                    {
                        return BattleHelper.IsInRegion(teamPosition,region);
                    }
                }
                else
                {
                    BattleDebug.LogError("Region is null " + regionId );
                }
            }
            return false;
        }

        private int GetConfigValue(List<int> array,int index)
        {
            if (index >= array.Count)
            {
                return 0;
            }
            return array[index];
        }

        private Vector3 GetPosition(int pointId,float radius = 0)
        {
            if (pointId >= 0)
            {
                return StageManager.Instance.GetMapPoint(pointId);
            }

            if (radius == 0)
            {
                radius = 45;
            }
            return BattleHelper.GetRandomPoint(radius);
        }

        private Vector3 GetSpawnPosition(int pointId)
        {
            if (pointId >= 0)
            {
                return StageManager.Instance.GetMapPoint(pointId);
            }
            return StageManager.Instance.GetSpawnPoint();
        }

        public void TriggerInteractable(int index)
        {
            if (interactableDic.TryGetValue(index, out var data))
            {
                data.Trigger();
            }
        }
        
        public void TriggerEvent(RpgMissionStageEventConfig config,BattleEventData eventData = null,MapInteractableData interactableData = null)
        {
            if (!SurvivorManager.isEventActive)
            {
                return;
            }
            //BattleDebug.LogError("TriggerEvent " + config.id);
            if (config.event_trigger == (int)EBattleEventType.SpawnEnemy)
            {
                var type = GetConfigValue(config.event_trigger_value, 0);
                if (type == (int)ESpawnType.RandomGroup)
                {
                    var positionId = GetConfigValue(config.event_condition_value, 3);
                    var radius = GetConfigValue(config.event_condition_value, 4);
                    var position = GetSpawnPosition(positionId);
                    var groupId = GetConfigValue(config.event_trigger_value, 1);
                    var group = BattleConfigManager.Instance.GetEnemyRandomGroupConfig(groupId);
                }
                else if (type == (int)ESpawnType.CertainGroup)
                {
                    var positionId = GetConfigValue(config.event_trigger_value, 3);
                    var radius = GetConfigValue(config.event_condition_value, 4);
                    var position = GetSpawnPosition(positionId);
                    var forward = StageManager.Instance.GetMapPointForward(positionId);
                    var groupId = GetConfigValue(config.event_trigger_value, 1);
                    FixedSpawn(1,groupId,position,forward);
                }
                else if (type == (int)ESpawnType.MapGroup)
                {
                    var groupId = GetConfigValue(config.event_trigger_value, 1);
                    StageManager.Instance.SpawnEnemyByGroupId(groupId);
                }
            }
            else if (config.event_trigger == (int)EBattleEventType.SpawnEnemyByDensity)
            {
                var densityCount = GetConfigValue(config.event_trigger_value, 0);
                var viewRadius = GetConfigValue(config.event_trigger_value, 1);
                var outViewRadius = GetConfigValue(config.event_trigger_value, 2);
                var groupId = GetConfigValue(config.event_trigger_value, 3);
                var initialDensity = GetConfigValue(config.event_trigger_value, 4);
                var densityIncreaseTime = GetConfigValue(config.event_trigger_value, 5) / 1000;
                ClearEnemyRandomSpawner();
                if (enemyRandomSpawner == null)
                {
                    enemyRandomSpawner = new EnemyRandomSpawner();
                }
                enemyRandomSpawner.Initialize(densityCount,viewRadius,outViewRadius,groupId,initialDensity,densityCount);
            }
            else if (config.event_trigger == (int)EBattleEventType.JoinTeam)
            {
                var heroId = GetConfigValue(config.event_trigger_value, 0);
                var range = GetConfigValue(config.event_trigger_value, 1);
                var position = BattleHelper.GetRandomPoint(range);
                var unit = StageManager.Instance.TeamGroup.CreateUnit(heroId);
                unit.Position = position;
            }
            else if (config.event_trigger == (int)EBattleEventType.SearchEnemy)
            {
                UnitManager.Instance.EnemyStartSearch();
            }
            else if (config.event_trigger == (int)EBattleEventType.Teleport)
            {
                StageManager.Instance.ResetTeamPosition(GetConfigValue(config.event_trigger_value, 0));
            }
            else if (config.event_trigger == (int)EBattleEventType.UpdateDynamicObject)
            {
                var objectIndex = GetConfigValue(config.event_trigger_value, 0);
                var active = GetConfigValue(config.event_trigger_value, 1) == 1;
                //MapManager.Instance.UpdateDynamicObjectActive(objectIndex,active);
            }
            else if (config.event_trigger == (int)EBattleEventType.UnlockFog)
            {
                StageManager.Instance.UnlockFog(GetConfigValue(config.event_trigger_value, 0));
            }
            else if (config.event_trigger == (int)EBattleEventType.CreateBullet)
            {
                var bulletId = GetConfigValue(config.event_trigger_value, 0);
                var pointId = GetConfigValue(config.event_trigger_value, 1);
                var fixedDamage = GetConfigValue(config.event_trigger_value, 2) * StageManager.Instance.missionConfig.attribute_ratio_hp * StageManager.Instance.missionConfig.attribute_ratio;
                var position = StageManager.Instance.GetMapPoint(pointId);
                var forward = StageManager.Instance.GetMapPointForward(pointId);
                StageManager.Instance.CreateEnvironmentBullet(bulletId, position, forward,(int)fixedDamage);
            }
            else if (config.event_trigger == (int)EBattleEventType.PlayTimeline)
            {
                var timelineName = config.string_value[0];
                if (config.string_value.Count > 1)
                {
                    if (ScreenOrientManager.GetInstance().GetScreenOrientationIsPortrait())
                    {
                        timelineName = config.string_value[1];
                    }
                }
                StageManager.Instance.PlayTimeline(timelineName);
            }
            else if (config.event_trigger == (int)EBattleEventType.ShowProgressUI)
            {
                var uiEventId = GetConfigValue(config.event_trigger_value, 0);
                if (uiEventId > 0)
                {
                    var uiConfig = BattleConfigManager.Instance.GetStageEventUIConfig(uiEventId);
                    if (uiConfig != null)
                    {
                        var type = uiConfig.data.x;
                        if (type == 1)//任务
                        {
                            var content = MissionManager.Instance.GetMissionContent(uiConfig.data.y,null);
                            var progress = MissionManager.Instance.GetMissionProgressValue(uiConfig.data.y);
                            MissionManager.Instance.BindMissionToUI(uiConfig.data.y);
                            StageManager.Instance.ShowProgressUI(BattleConfigManager.GetLangText(uiConfig.des),content,progress);
                        }
                        else if (type == 2) //事件
                        {
                            var evt = GetEventById(uiConfig.data.y);
                            evt.showUIEvent = true;
                            StageManager.Instance.ShowProgressUI(BattleConfigManager.GetLangText(uiConfig.des),GetUIEventContent(evt),GetUIEventProgress(evt));
                        }
                    }
                }
                else
                {
                    var typeId = GetConfigValue(config.event_trigger_value, 1);
                    if (typeId == 1) //触发警报UI
                    {
                        var isOpen = GetConfigValue(config.event_trigger_value, 2) == 1;
                        StageManager.Instance.UpdateFullScreenWarningUI(isOpen);
                    }
                    else if (typeId == 2)
                    {
                        var star = GetConfigValue(config.event_trigger_value, 2);
                        StageManager.Instance.UpdateStarUI(star);
                    }
                }
                
            }
            else if (config.event_trigger == (int)EBattleEventType.SwitchToRpg)
            {
                var levelId = GetConfigValue(config.event_trigger_value, 0);
                SurvivorManager.Instance.SwitchToRpg(levelId);
            }
            else if (config.event_trigger == (int)EBattleEventType.GuideDialogue)
            {
                if (eventData != null)
                {
                    eventData.isEventFinish = false;
                }
                var dialogueId = GetConfigValue(config.event_trigger_value, 0);
                SurvivorManager.Instance.ShowGuideDialogue(dialogueId, () =>
                {
                    if (eventData != null)
                    {
                        eventData.isEventFinish = true;
                    }
                });
            }
            else if (config.event_trigger == (int)EBattleEventType.JumpToStage)
            {
                StageManager.Instance.StageToNext(GetConfigValue(config.event_trigger_value, 0));
            }
            else if (config.event_trigger == (int)EBattleEventType.GetDollar)
            {
                var dollarCount = GetConfigValue(config.event_trigger_value, 0);
                var flyText = GetConfigValue(config.event_trigger_value, 1) == 1;
                var showEffect = GetConfigValue(config.event_trigger_value, 2) == 1;
                if (flyText)
                {
                    FlyTextManager.Instance.ShowFlyText(EFlyTextType.Dollar, StageManager.Instance.TeamGroup.Position, dollarCount.ToString());

                }
                if (showEffect)
                {
                    var position = StageManager.Instance.TeamGroup.Position;
                    var forward = StageManager.Instance.TeamGroup.Forward;
                    if (interactableData != null)
                    {
                        position = interactableData.transform.position;
                        forward = StageManager.Instance.TeamGroup.Position - position;
                    }
                    BattlePropsManager.Instance.CreateDropDollar(position, forward, dollarCount);
                }
                else
                {
                    SurvivorDataManager.Instance.AddDollar(dollarCount);
                }
            }
            else if (config.event_trigger == (int)EBattleEventType.CloseEvent)
            {
                for (int i = 0; i < eventList.Count; i++)
                {
                    var eventId = GetConfigValue(config.event_trigger_value, 0);
                    if (eventList[i].config.id == eventId)
                    {
                        eventList[i].valid = false;
                        if (BattleDebug.enableLog)
                        {
                            BattleDebug.Log("事件已关闭 " + eventId);
                        }
                        if (eventList[i].config.event_trigger == (int)EBattleEventType.SpawnEnemyByDensity)
                        {
                            ClearEnemyRandomSpawner();
                        }
                        if (eventList[i].showUIEvent)
                        {
                            StageManager.Instance.HideProgressUI();
                            eventList[i].showUIEvent = false;
                        }
                    }
                }
            }

            if (config.sub_event != null)
            {
                for (int i = 0; i < config.sub_event.Count; i++)
                {
                    var configId = config.sub_event[i];
                    var eventConfig = BattleConfigManager.Instance.GetStageEventConfig(configId);
                    TriggerEvent(eventConfig,eventData);
                }
            }
        }
        
        private BattleEventData GetEventById(int eventId)
        {
            for (int i = 0; i < eventList.Count; i++)
            {
                var data = eventList[i];
                if (data.config.id == eventId)
                {
                    return data;
                }
            }
            return null;
        }

        public void OnUnitRemoved(BattleUnit unit)
        {
            if (unit.team == 2)
            {
                enemyRandomSpawner?.RemoveEnemy(unit);
            }
        }

        public void OnUnitDead(BattleUnit unit)
        {
            if (unit.team == 2)
            {
                enemyRandomSpawner?.RemoveEnemy(unit);
            }
        }

        public void StartRandomSpawn(int densityCount = 8,float viewRadius = 12,float outViewRadius = 20,int groupId = 100102)
        {
            enemyRandomSpawner = new EnemyRandomSpawner();
            enemyRandomSpawner.Initialize(densityCount,viewRadius,outViewRadius,groupId);
        }

        public void FixedSpawn(int spawnCount, int groupId,Vector3 position,Vector3 forward)
        {
            var group = BattleConfigManager.Instance.GetEnemyGroupConfig(groupId);
            if (group != null)
            {
                var enemy = group.enemy;
                //出场方式
                var comingType = group.coming_type;
                if (comingType == (int)ESpawnComingType.None)
                {
                    for (int i = 0; i < enemy.Count; i++)
                    {
                        var enemyId = enemy[i].x;
                        var count = enemy[i].y;
                        for (int j = 0; j < count; j++)
                        {
                            StageManager.Instance.SpawnSingleEnemy(enemyId,position,forward,EEnemyAIType.SearchAllMap);
                        }
                    }
                }
                else if (comingType == (int)ESpawnComingType.ByPrefab)
                {
                    var prefabId = group.coming_param[0];
                    StageManager.Instance.SpawnEnemyByPrefab(enemy,(int)prefabId,position, StageManager.Instance.TeamGroup.Position - position,EEnemyAIType.SearchAllMap);
                }
            }
        }

        private string GetUIEventContent(BattleEventData data)
        {
            if (data.config.event_condition == (int)EBattleEventCondition.Timer)
            {
                var checkTime = data.addTime;
                if (data.lastTriggerTime != 0)
                {
                    checkTime = data.lastTriggerTime;
                }
                var time = GetConfigValue(data.config.event_condition_value, 0);
                var restTime = time - (TimeManager.time - checkTime);
                return BattleHelper.GetTimeString(restTime);
            }
            return string.Empty;
        }

        private float GetUIEventProgress(BattleEventData data)
        {
            if (data.config.event_condition == (int)EBattleEventCondition.Timer)
            {
                var checkTime = data.addTime;
                if (data.lastTriggerTime != 0)
                {
                    checkTime = data.lastTriggerTime;
                }
                var time = GetConfigValue(data.config.event_condition_value, 0);
                var restTime = time - (TimeManager.time - checkTime);
                return 1 - restTime / time;
            }
            return 0;
        }

        public bool needLoadTimeline = false;
        
        public void Clear()
        {
            /*if (enemyRandomSpawner != null)
            {
                enemyRandomSpawner.Stop();
                enemyRandomSpawner = null;
            }*/
            eventList.Clear();
            needLoadTimeline = false;
        }

        private void ClearEnemyRandomSpawner()
        {
            if (enemyRandomSpawner != null)
            {
                enemyRandomSpawner.Stop();
                enemyRandomSpawner = null;
            }
        }
        
        public override void Dispose()
        {
            ClearEnemyRandomSpawner();
            Clear();
        }
    }
}
